<template>
  <view class="cube-battle-room-container">
    <!-- 页面头部 -->
    <view class="page-header">
      <view class="header-top">
        <view class="back-btn" @click="goBack">
          <text class="back-icon">←</text>
        </view>
        <text class="page-title">魔方比赛房间</text>
      </view>
      
      <!-- 状态信息行 -->
      <view class="status-row">
        <!-- 房间信息 -->
        <view class="room-info">
          <view 
            class="room-status" 
            :class="getRoomStatusClass(roomStatus)"
            @click="openRoomStatusUpdateModal"
          >
            {{ getRoomStatusText(roomStatus) }}
          </view>
        </view>
        
        <!-- 当前用户席位信息 -->
        <view class="current-user-seat-section" v-if="currentUserSeatId">
          <view class="current-user-seat">
            <view class="seat-dot"></view>
            <text>席位: {{ currentUserSeatId }}</text>
          </view>
        </view>
        
        <!-- WebSocket连接状态 -->
        <view class="ws-status-section">
          <view 
            class="ws-status" 
            :class="{ 'connected': connected, 'disconnected': !connected }"
            @click="!connected && !connecting ? connectWebSocket() : null"
          >
            <view class="status-dot"></view>
            <text>{{ connected ? '已连接' : (connecting ? '连接中...' : '未连接') }}</text>
          </view>
        </view>
        
        <!-- 魔方连接状态 -->
        <view class="cube-status-section">
          <view 
            class="cube-status" 
            :class="{ 'connected': ble_is_connected, 'disconnected': !ble_is_connected }"
            @click="!ble_is_connected ? bleShowScan() : null"
          >
            <view class="status-dot"></view>
            <text>{{ ble_is_connected ? '魔方已连接' : '连接魔方' }}</text>
          </view>
        </view>
        
        <!-- 房间加入状态 -->
        <view class="room-join-section">
          <view 
            class="room-join-status" 
            :class="{ 'joined': isInRoom, 'not-joined': !isInRoom }"
            @click="!isInRoom ? joinRoom() : null"
          >
            <view class="status-dot"></view>
            <text>{{ isInRoom ? '已加入' : '加入房间' }}</text>
          </view>
        </view>
        
        <!-- 刷新按钮 -->
        <view class="refresh-section">
          <view 
            class="refresh-btn" 
            :class="{ 'loading': loading }"
            @click="refreshSeats"
          >
            <text class="refresh-icon">{{ loading ? '⟳' : '↻' }}</text>
          </view>
          
          <!-- 调试按钮 -->
          <view class="debug-btn" @click="testAllTranscubes">
            <text class="debug-icon">🐛</text>
          </view>
        </view>
      </view>
    </view>

    <!-- 当前回合规则展示区域 -->
    <view class="current-rule-section" v-if="currentRule">
      <view class="rule-card">
        <view class="rule-header">
          <text class="rule-title">当前回合规则</text>
          <view class="rule-progress">
            <text>{{ currentRuleIndex + 1 }}/{{ roomRules.length }}</text>
          </view>
        </view>
        <view class="rule-content">
          <view class="rule-path">
            <text class="path-label">路径:</text>
            <text class="path-value">{{ currentRule.startPoint }} → {{ currentRule.endPoint }}</text>
          </view>
          <view class="rule-details">
            <view class="detail-item">
              <text class="detail-label">准备时间:</text>
              <text class="detail-value">{{ currentRule.prepareTime ? currentRule.prepareTime / 1000 + 's' : '无限制' }}</text>
            </view>
            <view class="detail-item">
              <text class="detail-label">限制时间:</text>
              <text class="detail-value">{{ currentRule.limitTime ? currentRule.limitTime / 1000 + 's' : '无限制' }}</text>
            </view>
            <view class="detail-item">
              <text class="detail-label">计分模式:</text>
              <text class="detail-value">{{ getScoreModelText(currentRule.scoreModel) }}</text>
            </view>
            <view class="detail-item">
              <text class="detail-label">对战模式:</text>
              <text class="detail-value">{{ getBattleModelText(currentRule.battleModel) }}</text>
            </view>
          </view>
        </view>
      </view>
    </view>

    <!-- 席位网格 -->
    <view class="seats-grid-section">
        
        <view v-if="loading" class="loading-container">
          <view class="loading-spinner"></view>
          <text>加载席位中...</text>
        </view>
        
        <view v-else class="seats-container" :class="getSeatsContainerClass()">
          <view 
            class="seat-item" 
            v-for="(seat, index) in seatList" 
            :key="seat.id"
            :class="getSeatItemClass(seat)"
            @click="selectSeat(seat)"
          >
            <!-- 魔方显示 -->
            <view class="cube-container">
              <div class="card cube-box">
                <div class="cube3d" :id="`cube3d-${seat.id}`"></div>
              </div>
            </view>
            
            <!-- 席位信息 -->
            <view class="seat-info">
              <text class="seat-id">席位 {{ index + 1 }}</text>
              <text class="seat-owner">{{ seat.owner || '空闲' }}</text>
              <view 
                class="seat-status" 
                :class="getStatusClass(seat.status)"
                @click.stop="openSeatStatusUpdateModal(seat)"
                :style="{ cursor: seat.owner === currentUserId ? 'pointer' : 'default' }"
              >
                {{ getStatusText(seat.status) }}
              </view>
            </view>
            
            <!-- 当前用户标识 -->
            <view class="current-user-badge" v-if="seat.owner === currentUserId">
              <text>我</text>
            </view>
          </view>
        </view>
      
      <!-- 备用魔方容器 - 当没有席位或席位加载失败时使用 -->
      <view v-if="!loading && (!seatList || seatList.length === 0)" class="fallback-cube-container">
        <div class="card cube-box">
          <div class="cube3d" id="fallback-cube3d"></div>
        </div>
        <text class="fallback-text">等待席位加载...</text>
      </view>
    </view>

    <!-- 选中席位详情 -->
    <view class="selected-seat-detail" v-if="selectedSeat">
      <view class="detail-card">
        <view class="detail-header">
          <text class="detail-title">席位详情</text>
          <button class="close-btn" @click="selectedSeat = null">×</button>
        </view>
        <view class="detail-content">
          <view class="detail-row">
            <text class="detail-label">席位ID:</text>
            <text class="detail-value">{{ selectedSeat.id }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">所有者:</text>
            <text class="detail-value">{{ selectedSeat.owner || '未分配' }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">状态:</text>
            <view class="detail-status" :class="getStatusClass(selectedSeat.status)">
              {{ getStatusText(selectedSeat.status) }}
            </view>
          </view>
          <view class="detail-row">
            <text class="detail-label">角色:</text>
            <text class="detail-value">{{ getRoleText(selectedSeat.role) }}</text>
          </view>
          <view class="detail-row">
            <text class="detail-label">签到时间:</text>
            <text class="detail-value">{{ formatDate(selectedSeat.signTime) }}</text>
          </view>
        </view>
        <view class="detail-actions" v-if="selectedSeat.owner === currentUserId">
          <button class="action-btn primary" @click="goToSeatDetail(selectedSeat)">进入比赛</button>
          <button class="action-btn secondary" @click="leaveSeat(selectedSeat)">离开席位</button>
          
          <!-- 蓝牙控制区域 -->
          <view class="ble-controls">
            <view class="ble-control-title">蓝牙控制</view>
            <view class="ble-control-buttons">
              <button class="ble-btn connect" @click="bleShowScan" :disabled="ble_is_connected">
                {{ ble_is_connected ? '已连接' : '连接设备' }}
              </button>
              <button class="ble-btn disconnect" @click="bleDisconnect" :disabled="!ble_is_connected">
                断开设备
              </button>
              <button class="ble-btn reset" @click="cubeReset" :disabled="!ble_is_connected">
                魔方复原
              </button>
            </view>
            <!-- 设备状态信息 -->
            <view class="ble-status" v-if="ble_is_connected">
              <view class="status-item">
                <text class="status-label">连接状态:</text>
                <text class="status-value connected">已连接</text>
              </view>
              <view class="status-item" v-if="battery.level !== undefined">
                <text class="status-label">电池电量:</text>
                <text class="status-value">{{ battery.level }}%</text>
              </view>
            </view>
          </view>
        </view>
      </view>
    </view>

    <!-- 房间状态更新模态框 -->
    <view class="modal-overlay" v-if="showRoomStatusUpdateModal" @click="closeRoomStatusUpdateModal">
      <view class="picker-modal-content" @click.stop>
        <view class="picker-modal-header">
          <text class="picker-modal-title">修改房间状态</text>
          <button class="close-btn" @click="closeRoomStatusUpdateModal">×</button>
        </view>
        <view class="modal-body">
          <view class="current-status-info">
            <text class="info-label">当前状态:</text>
            <view class="status-badge" :class="getRoomStatusClass(roomStatus)">
              {{ getRoomStatusText(roomStatus) }}
            </view>
          </view>
          <view class="next-status-section">
            <text class="section-title">选择下一个状态:</text>
            <view class="status-options">
              <view 
                class="status-option" 
                v-for="(status, index) in availableNextRoomStatuses" 
                :key="status.value"
                @click="selectNextRoomStatus(status.value)"
                :class="{ 'selected': selectedNextRoomStatus === status.value }"
              >
                <text class="option-text">{{ status.label }}</text>
                <view class="option-check" v-if="selectedNextRoomStatus === status.value">✓</view>
              </view>
            </view>
          </view>
        </view>
        <view class="modal-footer">
          <button class="cancel-btn" @click="closeRoomStatusUpdateModal">取消</button>
          <button class="submit-btn" @click="updateRoomStatus" :disabled="updatingRoomStatus">
            {{ updatingRoomStatus ? '更新中...' : '确认更新' }}
          </button>
        </view>
      </view>
    </view>
    
    <!-- 席位状态更新模态框 -->
    <view class="modal-overlay" v-if="showSeatStatusUpdateModal" @click="closeSeatStatusUpdateModal">
      <view class="picker-modal-content" @click.stop>
        <view class="picker-modal-header">
          <text class="picker-modal-title">修改席位状态</text>
          <button class="close-btn" @click="closeSeatStatusUpdateModal">×</button>
        </view>
        <view class="modal-body">
          <view class="current-status-info">
            <text class="info-label">席位ID:</text>
            <text class="info-value">{{ currentSeatForStatus?.id }}</text>
          </view>
          <view class="current-status-info">
            <text class="info-label">当前状态:</text>
            <view class="status-badge" :class="getStatusClass(currentSeatForStatus?.status)">
              {{ getStatusText(currentSeatForStatus?.status) }}
            </view>
          </view>
          <view class="next-status-section">
            <text class="section-title">选择下一个状态:</text>
            <view class="status-options">
              <view 
                class="status-option" 
                v-for="(status, index) in availableNextSeatStatuses" 
                :key="status.value"
                @click="selectNextSeatStatus(status.value)"
                :class="{ 'selected': selectedNextSeatStatus === status.value }"
              >
                <text class="option-text">{{ status.label }}</text>
                <view class="option-check" v-if="selectedNextSeatStatus === status.value">✓</view>
              </view>
            </view>
          </view>
        </view>
        <view class="modal-footer">
          <button class="cancel-btn" @click="closeSeatStatusUpdateModal">取消</button>
          <button class="submit-btn" @click="updateSeatStatus" :disabled="updatingSeatStatus">
            {{ updatingSeatStatus ? '更新中...' : '确认更新' }}
          </button>
        </view>
      </view>
    </view>

  </view>
</template>

<script setup>
import { ref, onMounted, onUnmounted, computed, nextTick } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { MatchRoomSeatAPI, MatchRoomAPI, BattleAPI, MatchRoomRuleAPI } from '@/api/battle.js'
import { useUserStore } from '@/stores/user.js'
import { useCubeStore } from '@/stores/cube.js'
import { useTimeStore } from '@/stores/time.js'
import globalWebSocket from '@/utils/globalWebSocket.js'
import { mCall, mBus } from '@/utils/mCall.js'
import { CubeMap } from '@/utils/common.js'
import cube3d from '@/utils/cube3d.js'
import vmCube from '@/utils/solve.js'

const userStore = useUserStore()
const cubeStore = useCubeStore()
const timeStore = useTimeStore()

// 页面参数
const roomId = ref('')
const roomName = ref('')
const roomStatus = ref(1)
const isInRoom = ref(false)
const testSeats = ref(0) // 测试模式下的席位数量
const use3DCube = ref(true) // 是否使用3D魔方

// 席位相关
const seatList = ref([])
const selectedSeat = ref(null)
const loading = ref(false)

// 房间规则相关
const roomRules = ref([])
const currentRuleIndex = ref(0)
const currentRule = computed(() => roomRules.value[currentRuleIndex.value] || null)

// WebSocket相关
const socketAdapter = ref(null)
const connected = ref(false)
const connecting = ref(false)

// 蓝牙相关
const ble_is_connected = ref(false)
const ble_has_permission = ref(false)
const equipment = ref([])
const battery = ref({})

// 魔方控制相关
const cubeMoves = ref([])
const VmCube = new vmCube()
let cubeGames = new Map() // 使用Map以席位ID作为key，支持多个魔方实例
let faceLetsTime = 0

// 当前用户ID
const currentUserId = computed(() => userStore.userInfo?.id || `user-${Date.now()}`)

// 当前用户的席位ID
const currentUserSeatId = ref(null)

// 更新当前用户的席位ID
const updateCurrentUserSeatId = () => {
  const userSeat = seatList.value.find(seat => seat.owner === currentUserId.value)
  if (userSeat) {
    currentUserSeatId.value = userSeat.id
    console.log('当前用户席位ID已更新:', currentUserSeatId.value)
  } else {
    currentUserSeatId.value = null
    console.log('当前用户未占用任何席位')
  }
}

// 初始化WebSocket连接
const initWebSocket = async () => {
  try {
    console.log('初始化WebSocket连接...')
    socketAdapter.value = await globalWebSocket.getConnection()
    connected.value = globalWebSocket.isConnected()
    
    if (socketAdapter.value && connected.value) {
      // 监听席位状态变更
      socketAdapter.value.on('room_seat_status_change', (data) => {
        console.log('收到席位状态变更:', data)
        refreshSeats()
      })
      
      // 监听房间状态变更
      socketAdapter.value.on('room_status_change', (data) => {
        console.log('收到房间状态变更:', data)
        fetchRoomInfo()
      })
      
      // 监听魔方转动广播
      socketAdapter.value.on('player_cube_move', (data) => {
        console.log('收到魔方转动广播:', data)
        // 可以在这里更新对应席位的魔方状态
      })
    }
  } catch (error) {
    console.error('初始化WebSocket失败:', error)
    connected.value = false
  }
}

// 连接WebSocket
const connectWebSocket = async () => {
  connecting.value = true
  try {
    await initWebSocket()
    if (connected.value) {
      uni.showToast({ title: 'WebSocket连接成功', icon: 'success' })
    } else {
      throw new Error('连接失败')
    }
  } catch (error) {
    uni.showToast({ title: error.message || '连接失败', icon: 'none' })
  } finally {
    connecting.value = false
  }
}

// 断开WebSocket
const disconnectWebSocket = () => {
  globalWebSocket.disconnect()
  socketAdapter.value = null
  connected.value = false
  uni.showToast({ title: 'WebSocket已断开', icon: 'success' })
}

// 获取房间信息
const fetchRoomInfo = async () => {
  if (!roomId.value) {
    console.warn('无法获取房间信息：房间ID为空')
    return
  }
  
  console.log('开始获取房间信息，房间ID:', roomId.value)
  try {
    const result = await MatchRoomAPI.page({
      matchRoomId: roomId.value,
      pageNum: 0,
      pageSize: 1
    })
    
    console.log('房间信息API响应:', result)
    
    if (result.code === 0 && result.data) {
      const roomData = Array.isArray(result.data) ? result.data[0] : result.data.list?.[0]
      if (roomData) {
        roomStatus.value = roomData.status || 1
        console.log('获取到房间状态:', {
          code: result.code,
          roomData: roomData,
          status: roomStatus.value,
          statusText: getRoomStatusText(roomStatus.value)
        })
      } else {
        console.warn('房间数据为空或格式不正确')
      }
    } else {
      console.warn('获取房间信息失败:', result.msg || '未知错误')
    }
  } catch (error) {
    console.error('获取房间信息失败:', error)
  }
}

// 生成测试席位数据
const generateTestSeats = () => {
  console.log('开始生成测试席位，数量:', testSeats.value)
  loading.value = true
  
  setTimeout(() => {
    const seats = []
    const statuses = [0, 1, 2, 3, 4, 5, 6] // 各种状态
    const owners = ['', '玩家A', '玩家B', '玩家C', '玩家D', '玩家E', '玩家F', '玩家G', '玩家H']
    
    for (let i = 0; i < testSeats.value; i++) {
      const status = statuses[Math.floor(Math.random() * statuses.length)]
      const owner = status === 0 ? '' : owners[Math.floor(Math.random() * owners.length)]
      
      seats.push({
        id: `test-seat-${i + 1}`,
        owner: owner,
        status: status,
        role: 1,
        event: 0,
        matchRoomId: roomId.value,
        signTime: Date.now() - Math.random() * 86400000, // 随机时间
        createTime: Date.now() - Math.random() * 86400000 * 7 // 随机创建时间
      })
    }
    
    seatList.value = seats
    loading.value = false
    console.log('生成测试席位数据完成:', {
      requestedCount: testSeats.value,
      generatedCount: seats.length,
      seats: seats
    })
    // 更新当前用户的席位ID
    updateCurrentUserSeatId()
  }, 500) // 模拟加载延迟
}

// 获取席位列表
const fetchSeatList = async () => {
  if (!roomId.value) {
    console.warn('无法获取席位列表：房间ID为空')
    return
  }
  
  console.log('开始获取席位列表，房间ID:', roomId.value)
  loading.value = true
  try {
    const result = await MatchRoomSeatAPI.page({
      matchRoomId: roomId.value,
      pageNum: 0,
      pageSize: 100
    })
    
    console.log('席位列表API响应:', result)
    
    if (result.code === 0) {
      seatList.value = result.data?.list || result.data || []
      console.log('获取到席位列表:', {
        code: result.code,
        data: result.data,
        seatList: seatList.value,
        count: seatList.value.length
      })
    } else {
      seatList.value = []
      throw new Error(result.msg || '获取席位失败')
    }
  } catch (error) {
    console.error('获取席位失败:', error)
    seatList.value = []
    uni.showToast({
      title: error.message || '获取席位失败',
      icon: 'none'
    })
  } finally {
    loading.value = false
    // 更新当前用户的席位ID
    updateCurrentUserSeatId()
  }
}

// 获取房间规则
const fetchRoomRules = async () => {
  if (!roomId.value) return
  
  try {
    const result = await MatchRoomRuleAPI.page({
      matchRoomId: roomId.value,
      pageNum: 0,
      pageSize: 100
    })
    
    if (result.code === 0 && result.data) {
      const ruleList = result.data.list || result.data || []
      roomRules.value = ruleList.sort((a, b) => (a.sort || 0) - (b.sort || 0))
      console.log('获取到房间规则:', roomRules.value)
    } else {
      roomRules.value = []
    }
  } catch (error) {
    console.error('获取房间规则失败:', error)
    roomRules.value = []
  }
}

// 刷新席位
const refreshSeats = () => {
  fetchSeatList()
}

// 加入房间
const joinRoom = async () => {
  if (!roomId.value) {
    uni.showToast({ title: '房间ID不存在', icon: 'none' })
    return
  }
  
  try {
    uni.showLoading({ title: '正在加入房间...' })
    const result = await BattleAPI.joinRoom({
      appId: 1,
      channel: 10001,
      matchRoomId: roomId.value,
      pageNum: 0,
      pageSize: 10
    })
    
    if (result.code === 0) {
      uni.showToast({ title: '加入房间成功', icon: 'success' })
      isInRoom.value = true
      fetchSeatList()
      
      // 发送WebSocket消息
      if (socketAdapter.value && connected.value) {
        socketAdapter.value.sendRoomStatusChange(roomId.value, 1)
      }
    } else {
      throw new Error(result.msg || '加入房间失败')
    }
  } catch (error) {
    uni.showToast({ title: error.message || '加入房间失败', icon: 'none' })
  } finally {
    uni.hideLoading()
  }
}

// 选择席位
const selectSeat = async (seat) => {
  // 如果点击的是当前用户的席位，显示详情
  if (seat.owner === currentUserId.value) {
    selectedSeat.value = seat
    return
  }
  
  // 如果席位空闲，尝试加入
  if (seat.status === 0) {
    try {
      uni.showLoading({ title: '加入席位中...' })
      
      const result = await BattleAPI.updateRoomSeatStatus({
        matchRoomSeatId: seat.id,
        event: 1 // 占用席位
      })
      
      if (result.success) {
        uni.showToast({ title: '已加入席位', icon: 'success' })
        // 刷新席位列表
        await fetchSeatList()
      } else {
        uni.showToast({ title: result.message || '加入席位失败', icon: 'none' })
      }
    } catch (error) {
      console.error('加入席位失败:', error)
      uni.showToast({ title: '加入席位失败', icon: 'none' })
    } finally {
      uni.hideLoading()
    }
  } else if (seat.status === 1 && seat.owner === currentUserId.value) {
    // 如果席位已被当前用户占用，显示准备状态
    try {
      uni.showLoading({ title: '准备中...' })
      
      const result = await BattleAPI.updateRoomSeatStatus({
        matchRoomSeatId: seat.id,
        event: 2 // 准备
      })
      
      if (result.success) {
        uni.showToast({ title: '已准备', icon: 'success' })
        await fetchSeatList()
      } else {
        uni.showToast({ title: result.message || '准备失败', icon: 'none' })
      }
    } catch (error) {
      console.error('准备失败:', error)
      uni.showToast({ title: '准备失败', icon: 'none' })
    } finally {
      uni.hideLoading()
    }
  } else if (seat.status === 2 && seat.owner === currentUserId.value) {
    // 如果席位已准备，取消准备
    try {
      uni.showLoading({ title: '取消准备中...' })
      
      const result = await BattleAPI.updateRoomSeatStatus({
        matchRoomSeatId: seat.id,
        event: 1 // 回到占用状态
      })
      
      if (result.success) {
        uni.showToast({ title: '已取消准备', icon: 'success' })
        await fetchSeatList()
      } else {
        uni.showToast({ title: result.message || '取消准备失败', icon: 'none' })
      }
    } catch (error) {
      console.error('取消准备失败:', error)
      uni.showToast({ title: '取消准备失败', icon: 'none' })
    } finally {
      uni.hideLoading()
    }
  } else {
    // 其他情况显示席位详情
    selectedSeat.value = seat
  }
}

// 切换席位状态
const switchSeatStatus = async (seat) => {
  // 只有当前用户才能切换自己的席位状态
  if (seat.owner !== currentUserId.value) {
    return
  }
  
  try {
    let nextEvent = 0
    let loadingTitle = ''
    
    // 根据当前状态确定可用的状态转换选项
    const availableTransitions = getAvailableTransitions(seat.status)
    
    if (availableTransitions.length === 0) {
      uni.showToast({ 
        title: `当前状态[${getStatusText(seat.status)}]没有可用的操作`, 
        icon: 'none' 
      })
      return
    }
    
    // 如果有多个选项，让用户选择
    if (availableTransitions.length > 1) {
      const actionNames = availableTransitions.map(transition => ({
        event: transition.event,
        name: transition.name,
        description: transition.description
      }))
      
      // 显示操作选择弹窗
      const selectedAction = await showActionSelector(actionNames)
      if (!selectedAction) return
      
      nextEvent = selectedAction.event
      loadingTitle = selectedAction.description
    } else {
      // 只有一个选项，直接使用
      const transition = availableTransitions[0]
      nextEvent = transition.event
      loadingTitle = transition.description
    }
    
    // 检查是否是有效的状态转换
    if (!isValidStatusTransition(seat.status, nextEvent)) {
      uni.showToast({ 
        title: `当前状态[${getStatusText(seat.status)}]不支持此操作`, 
        icon: 'none' 
      })
      return
    }
    
    uni.showLoading({ title: loadingTitle })
    
    const result = await BattleAPI.updateRoomSeatStatus({
      matchRoomSeatId: seat.id,
      event: nextEvent
    })
    
    if (result.success) {
      const statusText = getStatusText(nextEvent)
      uni.showToast({ title: `已切换到${statusText}`, icon: 'success' })
      // 刷新席位列表
      await fetchSeatList()
    } else {
      uni.showToast({ title: result.message || '状态切换失败', icon: 'none' })
    }
  } catch (error) {
    console.error('切换席位状态失败:', error)
    uni.showToast({ title: '状态切换失败', icon: 'none' })
    // 如果是状态机错误，给出更友好的提示
    if (error.message && error.message.includes('状态机错误')) {
      uni.showToast({ 
        title: '状态转换不符合规则，请检查当前状态', 
        icon: 'none',
        duration: 3000
      })
    }
  } finally {
    uni.hideLoading()
  }
}

// 进入席位详情
const goToSeatDetail = (seat) => {
  uni.navigateTo({
    url: `/views/seat-detail?seatId=${seat.id}&seatName=${encodeURIComponent(seat.owner || '席位' + seat.id)}`
  })
}

// 离开席位
const leaveSeat = (seat) => {
  uni.showModal({
    title: '确认离开',
    content: '确定要离开当前席位吗？',
    success: async (res) => {
      if (res.confirm) {
        try {
          await BattleAPI.updateRoomSeatStatus({
            matchRoomSeatId: seat.id,
            event: 6 // 离开
          })
          
          uni.showToast({ title: '已离开席位', icon: 'success' })
          selectedSeat.value = null
          fetchSeatList()
        } catch (error) {
          uni.showToast({ title: '离开席位失败', icon: 'none' })
        }
      }
    }
  })
}

// 蓝牙相关方法
const bleShowScan = () => {
  mCall('ble_show_scan')
  
  equipment.value = []
  if (!equipment.value.length) {
    const inter = setInterval(() => {
      if (equipment.value.length) {
        clearInterval(inter)
      } else {
        getEquipment()
        getBattery()
      }
    }, 5000)
  }
}

const bleDisconnect = () => {
  mCall('ble_disconnect', '')
}

const getEquipment = () => {
  mCall('sendJSONData', {
    adress: '',
    data: { protoId: 3 }
  })
}

const getBattery = () => {
  mCall('sendJSONData', {
    adress: '',
    data: { protoId: 8 }
  })
}

// 设置魔方面
const setFace = (data) => {
  cubeStore.onFace(data)
  // 更新所有魔方实例以保持同步
  updateAllCubes('setFaceLetsInPlaying', data)
}

// 魔方复原重置
const cubeReset = () => {
  mCall('sendJSONData', {
    adress: '',
    data:{
      protoId: 6,
      step: 1,
      count: 28,
    }
  })
  
  // 发送魔方复原命令
  mCall('sendJSONData', {
    adress: '',
    data:{
      protoId: 3,
      step: 1,
      count: 28,
    }
  })
  
  // 更新魔方显示
  const primary = getPrimaryCubeGame()
  if (primary && primary.facelets) {
    try {
      primary.facelets.setFaceLets('UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB')
    } catch (error) {
      console.error('魔方复原显示失败:', error)
    }
  }
}

// 完成比赛
const onComplete = () => {
  console.log('比赛完成')
  // 这里可以添加比赛完成后的处理逻辑
  // 比如更新席位状态、显示完成提示等
}

// 观察计时
const onStopWatch = (num = 0) => {
  console.log('观察计时:', num)
  // 这里可以添加观察计时的处理逻辑
  // 比如更新计时器显示、播放音效等
}

// 工具函数

// 验证状态转换是否有效
const isValidStatusTransition = (currentStatus, nextEvent) => {
  // 定义允许的状态转换规则
  const validTransitions = {
    0: [1],           // 空闲 -> 占用
    1: [2, 0],        // 占用 -> 准备 或 空闲
    2: [3, 1],        // 准备 -> 赛前准备 或 占用
    3: [4, 2],        // 赛前准备 -> 策略规划 或 准备
    4: [5, 3],        // 策略规划 -> 比赛 或 赛前准备
    5: [6, 4],        // 比赛 -> 比赛结束 或 策略规划
    6: [0, 5]         // 比赛结束 -> 空闲 或 比赛
  }
  
  const allowedEvents = validTransitions[currentStatus] || []
  return allowedEvents.includes(nextEvent)
}

// 获取当前状态可用的转换选项
const getAvailableTransitions = (currentStatus) => {
  const transitions = {
    0: [ // 空闲
      { event: 1, name: '加入席位', description: '加入席位中...' }
    ],
    1: [ // 占用
      { event: 2, name: '准备', description: '准备中...' },
      { event: 0, name: '离开席位', description: '离开席位中...' }
    ],
    2: [ // 准备
      { event: 3, name: '赛前准备', description: '赛前准备中...' },
      { event: 1, name: '取消准备', description: '取消准备中...' }
    ],
    3: [ // 赛前准备
      { event: 4, name: '策略规划', description: '策略规划中...' },
      { event: 2, name: '返回准备', description: '返回准备中...' }
    ],
    4: [ // 策略规划
      { event: 5, name: '开始比赛', description: '进入比赛中...' },
      { event: 3, name: '返回赛前准备', description: '返回赛前准备中...' }
    ],
    5: [ // 比赛
      { event: 6, name: '结束比赛', description: '结束比赛中...' },
      { event: 4, name: '返回策略规划', description: '返回策略规划中...' }
    ],
    6: [ // 比赛结束
      { event: 0, name: '重置席位', description: '重置席位中...' },
      { event: 5, name: '重新比赛', description: '重新比赛中...' }
    ]
  }
  
  return transitions[currentStatus] || []
}

// 显示操作选择弹窗
const showActionSelector = (actions) => {
  return new Promise((resolve) => {
    const actionList = actions.map(action => action.name)
    
    uni.showActionSheet({
      itemList: actionList,
      success: (res) => {
        const selectedAction = actions[res.tapIndex]
        resolve(selectedAction)
      },
      fail: () => {
        resolve(null)
      }
    })
  })
}

const getStatusText = (status) => {
  const statusMap = {
    0: '空闲',
    1: '占用',
    2: '准备',
    3: '赛前准备',
    4: '策略规划',
    5: '比赛',
    6: '比赛结束',
    99: '异常'
  }
  return statusMap[status] || '未知'
}

const getStatusClass = (status) => {
  const statusClassMap = {
    0: 'status-idle',
    1: 'status-occupy',
    2: 'status-ready',
    3: 'status-prepare',
    4: 'status-plan',
    5: 'status-matching',
    6: 'status-end',
    99: 'status-error'
  }
  return statusClassMap[status] || 'status-unknown'
}

const getRoomStatusText = (status) => {
  const roomStatusMap = {
    1: '等待',
    2: '准备',
    3: '倒计时',
    4: '开始比赛',
    5: '结束比赛',
    6: '暂停',
    7: '取消',
    8: '异常'
  }
  return roomStatusMap[status] || '未知'
}

const getRoomStatusClass = (status) => {
  const roomStatusClassMap = {
    1: 'status-wait',
    2: 'status-prepare',
    3: 'status-countdown',
    4: 'status-start',
    5: 'status-stop',
    6: 'status-pause',
    7: 'status-cancel',
    8: 'status-error'
  }
  return roomStatusClassMap[status] || 'status-unknown'
}

// 房间状态转换规则（根据当前状态确定可用的下一个状态）
const getAvailableNextRoomStatuses = (currentStatus) => {
  // 状态转换规则（当前状态 -> 可用的下一个事件）
  const statusTransitions = {
    1: [1, 9, 99], // 等待 -> 玩家加入/取消比赛/发生异常
    2: [3, 9, 99], // 准备 -> 所有席位准备就绪/取消比赛/发生异常
    3: [5, 6, 9, 99], // 倒计时 -> 开始比赛/暂停比赛/取消比赛/发生异常
    4: [6, 8, 9, 99], // 开始比赛 -> 暂停比赛/结束比赛/取消比赛/发生异常
    5: [2, 9, 10, 99], // 结束比赛 -> 等待/取消比赛/重新开始比赛/发生异常
    6: [7, 9, 99], // 暂停 -> 恢复比赛/取消比赛/发生异常
    7: [2, 99], // 取消 -> 等待/发生异常
    8: [2, 7, 10, 99] // 异常 -> 等待/取消/重新开始比赛/发生异常
  }
  
  const availableEvents = statusTransitions[currentStatus] || []
  return availableEvents.map(event => ({
    value: event, // 直接使用事件值
    label: getRoomEventText(event) || '未知事件'
  }))
}

// 获取房间事件文本
const getRoomEventText = (event) => {
  const eventMap = {
    1: '玩家加入',
    2: '等待',
    3: '所有席位准备就绪',
    5: '开始比赛',
    6: '暂停比赛',
    7: '恢复比赛',
    8: '结束比赛',
    9: '取消比赛',
    10: '重新开始比赛',
    99: '发生异常'
  }
  return eventMap[event] || '未知事件'
}

// 席位状态管理相关数据
const showSeatStatusUpdateModal = ref(false)
const updatingSeatStatus = ref(false)
const selectedNextSeatStatus = ref(null)
const currentSeatForStatus = ref(null)
const availableNextSeatStatuses = ref([])

// 席位事件选项
const eventOptions = [
  '加入',           // 0: JOIN
  '准备',           // 1: READY
  '开始赛前准备',    // 2: START_PREPARE
  '策略规划',       // 3: STRATEGY_PLANNING
  '开始比赛',       // 4: START_GAME
  '结束比赛',       // 5: END_GAME
  '离开',           // 6: LEAVE
  '发生异常',       // 7: ERROR_OCCURRED
  '重新开始比赛'    // 8: RESTART_GAME
]

// 席位状态转换规则（根据当前状态确定可用的下一个状态）
const getAvailableNextSeatStatuses = (currentStatus) => {
  // 状态转换规则（当前状态 -> 可用的下一个事件）
  const statusTransitions = {
    0: [0, 7], // 空闲 -> 加入/发生异常
    1: [1, 7], // 占用 -> 准备/发生异常
    2: [2, 7], // 准备-等待比赛开始 -> 开始赛前准备/发生异常
    3: [3, 7], // 赛前准备 -> 策略规划/发生异常
    4: [4, 7], // 策略规划 -> 开始比赛/发生异常
    5: [5, 7], // 比赛 -> 结束比赛/发生异常
    6: [6, 7, 8], // 比赛结束 -> 离开/发生异常/重新开始比赛
    99: [0, 7, 8] // 异常 -> 加入/发生异常/重新开始比赛
  }
  
  const availableEvents = statusTransitions[currentStatus] || []
  return availableEvents.map(event => ({
    value: event, // 直接使用事件值
    label: eventOptions[event] || '未知事件'
  }))
}

// 打开席位状态更新模态框
const openSeatStatusUpdateModal = (seat) => {
  currentSeatForStatus.value = seat
  availableNextSeatStatuses.value = getAvailableNextSeatStatuses(seat.status)
  selectedNextSeatStatus.value = null
  showSeatStatusUpdateModal.value = true
}

// 关闭席位状态更新模态框
const closeSeatStatusUpdateModal = () => {
  showSeatStatusUpdateModal.value = false
  selectedNextSeatStatus.value = null
}

// 选择下一个席位状态
const selectNextSeatStatus = (status) => {
  selectedNextSeatStatus.value = status
}

// 更新席位状态
const updateSeatStatus = async () => {
  if (selectedNextSeatStatus.value === null) {
    uni.showToast({
      title: '请选择要更新的状态',
      icon: 'none'
    })
    return
  }
  if (!currentSeatForStatus.value) {
    uni.showToast({
      title: '席位信息不存在',
      icon: 'none'
    })
    return
  }
  
  // 保存event值，避免被清空
  const eventValue = selectedNextSeatStatus.value
  
  updatingSeatStatus.value = true
  try {
    const result = await BattleAPI.updateRoomSeatStatus({
      matchRoomSeatId: currentSeatForStatus.value.id,
      event: eventValue
    })
    if (result.code === 0) {
      uni.showToast({
        title: '席位状态更新成功',
        icon: 'success'
      })
      closeSeatStatusUpdateModal()
      // 重新获取席位列表以获取最新状态
      await fetchSeatList()
      // WebSocket发送席位状态变更消息（新协议）
      if (
        socketAdapter.value && 
        connected.value && 
        currentSeatForStatus.value && 
        currentSeatForStatus.value.id
      ) {
        socketAdapter.value.sendRoomSeatStatusChange(currentSeatForStatus.value.id, eventValue, roomId.value)
      }
      // 在所有异步操作完成后再清空
      currentSeatForStatus.value = null
    } else {
      throw new Error(result.msg || '席位状态更新失败')
    }
  } catch (error) {
    console.error('更新席位状态失败:', error)
    uni.showToast({
      title: error.message || '席位状态更新失败',
      icon: 'none'
    })
  } finally {
    updatingSeatStatus.value = false
  }
}

const getRoleText = (role) => {
  const roleMap = {
    1: '选手',
    2: '裁判',
    3: '观众',
    4: '主持人',
    5: '替补选手'
  }
  return roleMap[role] || '未知'
}

const getScoreModelText = (scoreModel) => {
  const scoreModelMap = {
    0: '不记分',
    1: '时间短',
    2: '时间长',
    3: '距离短',
    4: '距离长',
    5: '得分少',
    6: '得分多',
    7: '步数短',
    8: '步数长'
  }
  return scoreModelMap[scoreModel] || '未知'
}

const getBattleModelText = (battleModel) => {
  const battleModelMap = {
    0: '接力',
    1: '单回合',
    2: '多回合'
  }
  return battleModelMap[battleModel] || '未知'
}

const formatDate = (timestamp) => {
  if (!timestamp) return '未设置'
  const date = new Date(timestamp)
  return date.toLocaleString('zh-CN')
}

// 获取魔方面状态（根据席位状态返回不同的魔方面）
const getCubeFace = (seat) => {
  // 根据席位状态返回不同的魔方面状态
  // 这里可以根据实际需求调整
  // if (seat.status === 5) { // 比赛中
  //   return 'UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB' // 已还原状态
  // } else if (seat.status === 3 || seat.status === 4) { // 准备中
  //   return 'UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB' // 已还原状态
  // } else {
  //   return 'UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB' // 默认状态
  // }
}

// 获取魔方大小
const getCubeSize = () => {
  // 在测试模式下，使用 testSeats 的值
  const seatCount = testSeats.value > 0 ? testSeats.value : seatList.value.length
  
  if (seatCount === 1) {
    return 'large'
  } else if (seatCount === 2) {
    return 'large'
  } else if (seatCount <= 4) {
    return 'normal'
  } else if (seatCount <= 8) {
    return 'normal' // 5-8个席位，每行3个，使用normal大小
  } else if (seatCount <= 9) {
    return 'normal' // 9个席位，使用normal大小
  } else {
    return 'small' // 10个以上席位，使用small大小，让魔方更小
  }
}

// 获取席位容器样式类
const getSeatsContainerClass = () => {
  // 在测试模式下，使用 testSeats 的值，否则使用实际席位数量
  const seatCount = testSeats.value > 0 ? testSeats.value : (seatList.value?.length || 0)
  
  console.log('席位数量计算:', {
    testSeats: testSeats.value,
    seatListLength: seatList.value?.length || 0,
    finalSeatCount: seatCount
  })
  
  if (seatCount === 1) {
    return 'seats-single'
  } else if (seatCount === 2) {
    return 'seats-dual'
  } else if (seatCount <= 4) {
    return 'seats-quad'
  } else if (seatCount <= 8) {
    return 'seats-grid-3' // 5-8个席位，每行3个
  } else {
    return 'seats-grid-4' // 9个以上席位，每行4个
  }
}

// 获取席位样式类
const getSeatItemClass = (seat) => {
  const classes = []
  
  if (seat.owner === currentUserId.value) {
    classes.push('current-user')
  }
  
  if (seat.status === 5) { // 比赛中
    classes.push('active')
  }
  
  // 添加状态类名
  const statusClassMap = {
    0: 'status-idle',
    1: 'status-occupy',
    2: 'status-ready',
    3: 'status-prepare',
    4: 'status-plan',
    5: 'status-matching',
    6: 'status-end',
    99: 'status-error'
  }
  
  const statusClass = statusClassMap[seat.status]
  if (statusClass) {
    classes.push(statusClass)
  }
  
  return classes
}

// 返回上一页
const goBack = () => {
  uni.navigateBack()
}



// 页面加载
onLoad((options) => {
  console.log('页面加载参数:', options)
  
  if (options.roomId) {
    roomId.value = options.roomId
    roomName.value = decodeURIComponent(options.roomName || '')
    
    console.log('房间信息:', {
      roomId: roomId.value,
      roomName: roomName.value,
      testSeats: options.testSeats
    })
    
    // 检查是否为测试模式
    if (options.testSeats) {
      testSeats.value = parseInt(options.testSeats)
      console.log('测试模式，席位数量:', testSeats.value)
      generateTestSeats()
    } else {
      console.log('正常模式，开始获取房间信息')
      fetchRoomInfo()
      fetchSeatList()
      fetchRoomRules()
    }
  } else {
    console.warn('未提供房间ID参数')
  }
})

// 组件挂载
onMounted(async () => {
  await initWebSocket()
  
  // 等待 DOM 渲染完成后再初始化魔方游戏
  await nextTick()
  
  // 延迟一点时间确保 DOM 完全渲染
  setTimeout(() => {
    // 调试信息：检查席位数据
    console.log('当前席位列表:', seatList.value)
    console.log('席位数量:', seatList.value?.length)
    
    // 更新当前用户的席位ID
    updateCurrentUserSeatId()
    
    // 检查所有 .cube3d 元素
    const allCubeElements = document.querySelectorAll('.cube3d')
    console.log('找到的 .cube3d 元素数量:', allCubeElements.length)
    
    if (allCubeElements.length > 0) {
      // 显示所有找到的 cube3d 元素信息
      allCubeElements.forEach((el, index) => {
        console.log(`cube3d 元素 ${index}:`, {
          id: el.id,
          className: el.className,
          visible: el.offsetParent !== null
        })
      })
      
      // 为每个 cube3d 元素创建魔方游戏实例
      cubeGames.clear()
      allCubeElements.forEach((cubeElement, index) => {
        try {
          console.log(`初始化魔方 ${index + 1}，容器元素:`, cubeElement)
          const seatId = cubeElement.id.replace('cube3d-', '')
          const cubeGame = new cube3d({ el: `#${cubeElement.id}` })
          
          // 检查实例的完整性
          console.log(`魔方 ${index + 1} 实例检查:`, {
            seatId,
            hasTranscube: !!cubeGame.transcube,
            hasFacelets: !!cubeGame.facelets,
            hasControls: !!cubeGame.controls,
            hasWorld: !!cubeGame.world
          })
          
          cubeGames.set(seatId, cubeGame)
          console.log(`魔方 ${index + 1} 初始化成功，seatId=${seatId}`)
        } catch (error) {
          console.error(`魔方 ${index + 1} 初始化失败:`, error)
        }
      })
      
      console.log(`成功初始化 ${[...cubeGames.values()].filter(g => g).length} 个魔方实例`)
      console.log('所有魔方实例详情:', getAllCubeGames())
    } else {
      // 尝试查找备用魔方容器
      const fallbackElement = document.querySelector('#fallback-cube3d')
      if (fallbackElement) {
        console.log('使用备用魔方容器:', fallbackElement)
        try {
          cubeGames.clear()
          cubeGames.set('fallback', new cube3d({ el: '#fallback-cube3d' }))
          console.log('魔方游戏初始化成功（使用备用容器）')
        } catch (error) {
          console.error('魔方游戏初始化失败（备用容器）:', error)
          cubeGames.clear()
        }
      } else {
        console.warn('找不到任何 .cube3d 元素，魔方游戏将不会显示')
        console.warn('当前 DOM 中所有元素:', document.body.innerHTML.substring(0, 500))
        cubeGames.clear()
      }
    }
  }, 500) // 增加等待时间
  
  // 注册蓝牙事件监听
  mBus({
    ble_is_connected(res) {
      ble_is_connected.value = res.data
    },
    ble_has_permission(res) {
      ble_has_permission.value = res.data
    },
    // 接收转动魔方时的信息V2
			onReceiveJSONData(res) {
				console.log('onReceiveJSONData 被触发:', res)
				res = res.data ? res.data : res
				if (res) {
					switch (+res.protoId) {
						// 转动
						case 1:
							const name = CubeMap[res.formula]
							res.cubeName = name
              
							
							cubeStore.onMove(res)
							cubeMoves.value.push(name)
							
							// 尝试使用第一个可用的 transcube 实例
							let transcubeUsed = false
							for (const [seatId, game] of cubeGames.entries()) {
                if (game && game.transcube && seatId === currentUserSeatId.value) {
                  try {
                    // 尝试调用一个简单的转动来测试
                    console.log(`测试席位 ${seatId} 的 transcube...`)
                    game.transcube.trans(name)
                    console.log('席位 ${seatId}transcube 测试成功' )
                  } catch (error) {
                    // results.push({ seatId, status: 'error', message: `transcube 测试失败: ${error.message}` })
                    console.error(`席位 ${seatId} 的 transcube 测试失败:`, error)
                  }
                } else {
                  // results.push({ seatId, status: 'missing', message: '缺少 transcube 实例' })
                }
              }
							
							if (!transcubeUsed) {
								console.warn('没有可用的 transcube 实例进行转动')
							}
              
							// mCall('cube_get_facelets')
							VmCube.move(name)
							console.log('asString:', VmCube.asString())
							setFace(VmCube.asString())
							console.log('收到魔方转动数据', res)
							console.log('socketAdapter', socketAdapter.value, 'connected', connected.value)
							// WebSocket实时发送魔方转动消息
							if (socketAdapter.value && connected.value && res) {
								socketAdapter.value.sendCubeMove(
									res.cubeName, // move
									res.interval || 0, // interval
									res.step || 1,     // step
									res.rotate || 0,   // rotate
									res.modify || 0    // modify
								)
								console.log('已发送魔方转动消息')
							}
							// 检查魔方是否还原
							if ('UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB' == VmCube.asString()) {
								console.log('魔方已还原!')
								cubeStore.onResolved(true)
								if (timeStore.stage === 3) {
									onComplete();
									// mCall('cube_get_facelets')
								}
							}
							// 观察中
							if (timeStore.stage === 2) {
								onStopWatch(-1)
							}
							
							// 左右转动下一把
							if ([0, 4].includes(timeStore.stage)) {
								if (cubeMoves.value.length > 1) {
									let last = cubeMoves.value[cubeMoves.value.length - 2]
									if (name + '\'' === last || name === last + '\'') {
										cubeMoves.value = []
									}
								}
							}
							break;
						// 魔方复原重置
						case 2:
							if (timeStore.stage === 3) {
								onComplete();
								mCall('cube_get_facelets')
							}
							updateAllCubes('setFaceLets', 'UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB')
						// 同步状态
						case 3:
							
							break;
						// 电池电量
						case 4:
							battery.value = res
							break;
					
						default:
							break;
					}
				}
			},
    
    // 获取魔方面状态
    cube_get_facelets(res) {
      console.log('获取魔方面状态:', res)
      if (res && res.data) {
        setFace(res.data)
      }
    }
  })
})

// 组件卸载
onUnmounted(() => {
  console.log('cube-battle-room页面卸载')
})

// 房间状态管理相关数据
const showRoomStatusUpdateModal = ref(false)
const availableNextRoomStatuses = ref([])
const selectedNextRoomStatus = ref(null)
const updatingRoomStatus = ref(false)

// 打开房间状态更新模态框
const openRoomStatusUpdateModal = () => {
  availableNextRoomStatuses.value = getAvailableNextRoomStatuses(roomStatus.value)
  selectedNextRoomStatus.value = null
  showRoomStatusUpdateModal.value = true
}

// 关闭房间状态更新模态框
const closeRoomStatusUpdateModal = () => {
  showRoomStatusUpdateModal.value = false
  selectedNextRoomStatus.value = null
}

// 选择下一个房间状态
const selectNextRoomStatus = (status) => {
  selectedNextRoomStatus.value = status
}

// 更新房间状态
const updateRoomStatus = async () => {
  if (selectedNextRoomStatus.value === null) {
    uni.showToast({
      title: '请选择要更新的状态',
      icon: 'none'
    })
    return
  }
  
  const eventValue = selectedNextRoomStatus.value
  
  updatingRoomStatus.value = true
  try {
    const result = await BattleAPI.updateRoomStatus({
      matchRoomId: roomId.value,
      event: eventValue
    })
    
    if (result.success) {
      uni.showToast({
        title: '房间状态更新成功',
        icon: 'success'
      })
      
      closeRoomStatusUpdateModal()
      
      // 重新获取房间信息以获取最新状态
      await fetchRoomInfo()
    } else {
      throw new Error(result.message || '房间状态更新失败')
    }
  } catch (error) {
    console.error('更新房间状态失败:', error)
    uni.showToast({
      title: error.message || '房间状态更新失败',
      icon: 'none'
    })
  } finally {
    updatingRoomStatus.value = false
  }
}

// 获取主要的魔方游戏实例（用于控制逻辑）
const getPrimaryCubeGame = () => {
  // 返回第一个可用的实例
  for (const game of cubeGames.values()) {
    if (game) return game
  }
  return null
}

// 获取指定席位的魔方游戏实例
const getCubeGameBySeatId = (seatId) => {
  return cubeGames.get(seatId) || null
}

// 获取所有可用的魔方游戏实例（用于调试）
const getAllCubeGames = () => {
  const games = []
  for (const [seatId, game] of cubeGames.entries()) {
    if (game) {
      games.push({ 
        seatId, 
        game, 
        hasTranscube: !!game.transcube,
        isCurrentUser: seatId === currentUserSeatId.value
      })
    }
  }
  return games
}

// 更新所有魔方实例（用于同步显示）
const updateAllCubes = (action, data) => {
  console.log(`开始更新所有魔方实例，操作: ${action}，数据: ${data}`)
  console.log('当前魔方实例状态:', getAllCubeGames())
  
  let successCount = 0
  let failCount = 0
  
  for (const [seatId, game] of cubeGames.entries()) {
    if (game && game.facelets) {
      try {
        switch (action) {
          case 'setFaceLets':
            game.facelets.setFaceLets(data)
            successCount++
            console.log(`席位 ${seatId} 魔方更新成功: ${action}`)
            break
          case 'setFaceLetsInPlaying':
            game.facelets.setFaceLetsInPlaying(data)
            successCount++
            console.log(`席位 ${seatId} 魔方更新成功: ${action}`)
            break
          default:
            console.warn(`未知的魔方更新操作: ${action}`)
        }
      } catch (error) {
        failCount++
        console.error(`席位 ${seatId} 魔方更新失败: ${action}`, error)
      }
    } else {
      console.warn(`席位 ${seatId} 魔方实例不可用或缺少 facelets`)
    }
  }
  
  console.log(`魔方更新完成，成功: ${successCount}，失败: ${failCount}`)
}

// 测试所有魔方实例的 transcube 功能
const testAllTranscubes = () => {
  console.log('开始测试所有魔方实例的 transcube 功能...')
  const results = []
  
  for (const [seatId, game] of cubeGames.entries()) {
    if (game && game.transcube) {
      try {
        // 尝试调用一个简单的转动来测试
        console.log(`测试席位 ${seatId} 的 transcube...`)
        game.transcube.trans('R')
        results.push({ seatId, status: 'success', message: 'transcube 测试成功' })
      } catch (error) {
        results.push({ seatId, status: 'error', message: `transcube 测试失败: ${error.message}` })
        console.error(`席位 ${seatId} 的 transcube 测试失败:`, error)
      }
    } else {
      results.push({ seatId, status: 'missing', message: '缺少 transcube 实例' })
    }
  }
  
  console.log('transcube 测试结果:', results)
  return results
}
</script>

<style lang="scss" scoped>
.cube-battle-room-container {
  min-height: 100vh;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  padding: 20rpx;
}

.page-header {
  margin-bottom: 30rpx;
  
  .header-top {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 20rpx;
    margin-bottom: 20rpx;
    padding: 0 20rpx;
    
    .back-btn {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 60rpx;
      height: 60rpx;
      background: rgba(255, 255, 255, 0.1);
      border-radius: 50%;
      transition: all 0.3s ease;
      cursor: pointer;
      
      .back-icon {
        color: #fff;
        font-size: 32rpx;
        font-weight: bold;
      }
      
      &:hover {
        background: rgba(255, 255, 255, 0.2);
        transform: scale(1.1);
      }
      
      &:active {
        transform: scale(0.95);
        background: rgba(255, 255, 255, 0.3);
      }
    }
    
    .page-title {
      font-size: 36rpx;
      font-weight: bold;
      color: #fff;
      text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3);
      flex: 1;
      text-align: center;
    }
  }
  
  // 状态信息行样式
  .status-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20rpx;
    margin-top: 20rpx;
    padding: 0 20rpx;
    
    .room-info {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      
      .room-status {
        padding: 8rpx 16rpx;
        border-radius: 16rpx;
        font-size: 20rpx;
        font-weight: bold;
        color: #fff;
        cursor: pointer;
        transition: all 0.3s ease;
        white-space: nowrap;
        
        &:hover {
          transform: scale(1.05);
          box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2);
        }
        
        &:active {
          transform: scale(0.95);
        }
        
        &.status-1 { background: #28a745; }
        &.status-2 { background: #ffc107; }
        &.status-3 { background: #17a2b8; }
        &.status-4 { background: #6c757d; }
        &.status-5 { background: #dc3545; }
        &.status-6 { background: #fd7e14; }
        &.status-7 { background: #6f42c1; }
        &.status-8 { background: #e83e8c; }
      }
    }
    
    .current-user-seat-section {
      flex-shrink: 0;
      
      .current-user-seat {
        display: flex;
        align-items: center;
        gap: 6rpx;
        padding: 6rpx 12rpx;
        background: rgba(255, 193, 7, 0.2);
        border-radius: 16rpx;
        font-size: 20rpx;
        font-weight: bold;
        color: #ffc107;
        transition: all 0.3s ease;
        white-space: nowrap;
        
        .seat-dot {
          width: 10rpx;
          height: 10rpx;
          border-radius: 50%;
          background: #ffc107;
        }
        
        &:hover {
          background: rgba(255, 193, 7, 0.3);
          transform: scale(1.05);
        }
      }
    }
    
    .ws-status-section,
    .cube-status-section,
    .room-join-section {
      flex-shrink: 0;
      
      .ws-status,
      .cube-status,
      .room-join-status {
        display: flex;
        align-items: center;
        gap: 6rpx;
        padding: 6rpx 12rpx;
        border-radius: 16rpx;
        font-size: 20rpx;
        font-weight: bold;
        transition: all 0.3s ease;
        white-space: nowrap;
        
        .status-dot {
          width: 10rpx;
          height: 10rpx;
          border-radius: 50%;
        }
        
        &.connected {
          background: rgba(76, 175, 80, 0.2);
          color: #4caf50;
          cursor: default;
          
          .status-dot {
            background: #4caf50;
          }
        }
        
        &.disconnected {
          background: rgba(244, 67, 54, 0.2);
          color: #f44336;
          cursor: pointer;
          
          .status-dot {
            background: #f44336;
          }
          
          &:hover {
            background: rgba(244, 67, 54, 0.3);
            transform: scale(1.05);
          }
          
          &:active {
            transform: scale(0.95);
          }
        }
        
        &.joined {
          background: rgba(76, 175, 80, 0.2);
          color: #4caf50;
          cursor: default;
          
          .status-dot {
            background: #4caf50;
          }
        }
        
        &.not-joined {
          background: rgba(255, 193, 7, 0.2);
          color: #ffc107;
          cursor: pointer;
          
          .status-dot {
            background: #ffc107;
          }
          
          &:hover {
            background: rgba(255, 193, 7, 0.3);
            transform: scale(1.05);
          }
          
          &:active {
            transform: scale(0.95);
          }
        }
      }
    }
    
    .refresh-section {
      flex-shrink: 0;
      display: flex;
      gap: 15rpx;
      
      .refresh-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 56rpx;
        height: 56rpx;
        background: rgba(23, 162, 184, 0.2);
        border-radius: 50%;
        transition: all 0.3s ease;
        cursor: pointer;
        
        .refresh-icon {
          color: #17a2b8;
          font-size: 28rpx;
          font-weight: bold;
        }
        
        &:hover {
          background: rgba(23, 162, 184, 0.3);
          transform: scale(1.1);
        }
        
        &:active {
          transform: scale(0.95);
          background: rgba(23, 162, 184, 0.4);
        }
        
        &.loading {
          background: rgba(23, 162, 184, 0.4);
          
          .refresh-icon {
            animation: spin 1s linear infinite;
          }
        }
      }
      
      .debug-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 56rpx;
        height: 56rpx;
        background: rgba(255, 193, 7, 0.2);
        border-radius: 50%;
        transition: all 0.3s ease;
        cursor: pointer;
        
        .debug-icon {
          color: #ffc107;
          font-size: 24rpx;
        }
        
        &:hover {
          background: rgba(255, 193, 7, 0.3);
          transform: scale(1.1);
        }
        
        &:active {
          transform: scale(0.95);
          background: rgba(255, 193, 7, 0.4);
        }
      }
    }
  }
}

.current-rule-section {
  margin-bottom: 30rpx;
  
  .rule-card {
    background: rgba(255, 255, 255, 0.95);
    border-radius: 16rpx;
    padding: 24rpx;
    box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
    
    .rule-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 16rpx;
      
      .rule-title {
        font-size: 28rpx;
        font-weight: bold;
        color: #333;
      }
      
      .rule-progress {
        padding: 4rpx 12rpx;
        background: #667eea;
        color: #fff;
        border-radius: 12rpx;
        font-size: 20rpx;
        font-weight: bold;
      }
    }
    
    .rule-content {
      .rule-path {
        display: flex;
        align-items: center;
        margin-bottom: 12rpx;
        
        .path-label {
          font-size: 24rpx;
          color: #666;
          margin-right: 10rpx;
        }
        
        .path-value {
          font-size: 24rpx;
          color: #333;
          font-weight: bold;
        }
      }
      
      .rule-details {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8rpx;
        
        .detail-item {
          display: flex;
          justify-content: space-between;
          align-items: center;
          
          .detail-label {
            font-size: 22rpx;
            color: #666;
          }
          
          .detail-value {
            font-size: 22rpx;
            color: #333;
            font-weight: 500;
          }
        }
      }
    }
  }
}

.seats-grid-section {
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;
  

  
  .loading-container {
    text-align: center;
    padding: 60rpx;
    color: #fff;
    
    .loading-spinner {
      width: 60rpx;
      height: 60rpx;
      border: 4rpx solid rgba(255, 255, 255, 0.3);
      border-top: 4rpx solid #fff;
      border-radius: 50%;
      animation: spin 1s linear infinite;
      margin: 0 auto 20rpx;
    }
  }
  
  .seats-container {
    // 单个席位 - 全屏显示
    &.seats-single {
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 60vh;
      
      .seat-item {
        width: 80%;
        max-width: 500rpx;
        min-height: 500rpx;
        background: rgba(255, 255, 255, 0.95);
        border-radius: 24rpx;
        padding: 50rpx;
        text-align: center;
        position: relative;
        transition: all 0.3s ease;
        box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        
        .cube-container {
          margin-bottom: 30rpx;
          display: flex;
          justify-content: center;
          flex: 1;
          align-items: center;
        }
        
        .seat-info {
          .seat-id {
            display: block;
            font-size: 32rpx;
            color: #666;
            margin-bottom: 12rpx;
          }
          
          .seat-owner {
            display: block;
            font-size: 36rpx;
            color: #333;
            font-weight: bold;
            margin-bottom: 16rpx;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
          
          .seat-status {
            padding: 10rpx 20rpx;
            border-radius: 16rpx;
            font-size: 28rpx;
            font-weight: bold;
            
            &.status-idle { background: #d4edda; color: #155724; }
            &.status-occupy { background: #cce5ff; color: #004085; }
            &.status-ready { background: #fff3cd; color: #856404; }
            &.status-prepare { background: #d1ecf1; color: #0c5460; }
            &.status-plan { background: #e2e3e5; color: #383d41; }
            &.status-matching { background: #d4edda; color: #155724; }
            &.status-end { background: #f8d7da; color: #721c24; }
            &.status-error { background: #f8d7da; color: #721c24; }
          }
        }
      }
    }
    
    // 两个席位 - 左右展示
    &.seats-dual {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 30rpx;
      padding: 30rpx;
      width: 100%;
      box-sizing: border-box;
      
      .seat-item {
        flex: 1;
        max-width: 45%;
        min-width: 280rpx;
        min-height: 360rpx;
        background: rgba(255, 255, 255, 0.95);
        border-radius: 18rpx;
        padding: 25rpx;
        text-align: center;
        position: relative;
        transition: all 0.3s ease;
        box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.12);
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        
        .cube-container {
          margin-bottom: 16rpx;
          display: flex;
          justify-content: center;
          flex: 1;
          align-items: center;
          min-height: 200rpx;
        }
        
        .seat-info {
          .seat-id {
            display: block;
            font-size: 24rpx;
            color: #666;
            margin-bottom: 6rpx;
          }
          
          .seat-owner {
            display: block;
            font-size: 26rpx;
            color: #333;
            font-weight: bold;
            margin-bottom: 8rpx;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
          
          .seat-status {
            padding: 6rpx 12rpx;
            border-radius: 10rpx;
            font-size: 20rpx;
            font-weight: bold;
            
            &.status-idle { background: #d4edda; color: #155724; }
            &.status-occupy { background: #cce5ff; color: #004085; }
            &.status-ready { background: #fff3cd; color: #856404; }
            &.status-prepare { background: #d1ecf1; color: #0c5460; }
            &.status-plan { background: #e2e3e5; color: #383d41; }
            &.status-matching { background: #d4edda; color: #155724; }
            &.status-end { background: #f8d7da; color: #721c24; }
            &.status-error { background: #f8d7da; color: #721c24; }
          }
        }
      }
    }
    
    // 3-4个席位 - 4宫格展示
    &.seats-quad {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 30rpx;
      padding: 30rpx;
      
      .seat-item {
        min-width: 280rpx;
        min-height: 320rpx;
        background: rgba(255, 255, 255, 0.95);
        border-radius: 18rpx;
        padding: 30rpx;
        text-align: center;
        position: relative;
        transition: all 0.3s ease;
        box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.12);
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        
        .cube-container {
          margin-bottom: 20rpx;
          display: flex;
          justify-content: center;
          flex: 1;
          align-items: center;
        }
        
        .seat-info {
          .seat-id {
            display: block;
            font-size: 24rpx;
            color: #666;
            margin-bottom: 8rpx;
          }
          
          .seat-owner {
            display: block;
            font-size: 28rpx;
            color: #333;
            font-weight: bold;
            margin-bottom: 10rpx;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
          
          .seat-status {
            padding: 6rpx 12rpx;
            border-radius: 10rpx;
            font-size: 20rpx;
            font-weight: bold;
            
            &.status-idle { background: #d4edda; color: #155724; }
            &.status-occupy { background: #cce5ff; color: #004085; }
            &.status-ready { background: #fff3cd; color: #856404; }
            &.status-prepare { background: #d1ecf1; color: #0c5460; }
            &.status-plan { background: #e2e3e5; color: #383d41; }
            &.status-matching { background: #d4edda; color: #155724; }
            &.status-end { background: #f8d7da; color: #721c24; }
            &.status-error { background: #f8d7da; color: #721c24; }
          }
        }
      }
    }
    
    // 5-8个席位 - 每行3个
    &.seats-grid-3 {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 20rpx;
      padding: 20rpx;
      width: 100%;
      box-sizing: border-box;
      overflow: hidden;
      
      .seat-item {
        width: 100%;
        min-height: 280rpx;
        max-width: 100%;
        background: rgba(255, 255, 255, 0.95);
        border-radius: 16rpx;
        padding: 20rpx;
        text-align: center;
        position: relative;
        transition: all 0.3s ease;
        box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        box-sizing: border-box;
        overflow: hidden;
        
        .cube-container {
          margin-bottom: 16rpx;
          display: flex;
          justify-content: center;
          flex: 1;
          align-items: center;
        }
        
        .seat-info {
          .seat-id {
            display: block;
            font-size: 20rpx;
            color: #666;
            margin-bottom: 6rpx;
          }
          
          .seat-owner {
            display: block;
            font-size: 22rpx;
            color: #333;
            font-weight: bold;
            margin-bottom: 8rpx;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
          
          .seat-status {
            padding: 5rpx 10rpx;
            border-radius: 8rpx;
            font-size: 18rpx;
            font-weight: bold;
            
            &.status-idle { background: #d4edda; color: #155724; }
            &.status-occupy { background: #cce5ff; color: #004085; }
            &.status-ready { background: #fff3cd; color: #856404; }
            &.status-prepare { background: #d1ecf1; color: #0c5460; }
            &.status-plan { background: #e2e3e5; color: #383d41; }
            &.status-matching { background: #d4edda; color: #155724; }
            &.status-end { background: #f8d7da; color: #721c24; }
            &.status-error { background: #f8d7da; color: #721c24; }
          }
        }
      }
    }
    
    // 9个以上席位 - 每行4个
    &.seats-grid-4 {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 16rpx;
      padding: 20rpx;
      width: 100%;
      box-sizing: border-box;
      overflow: hidden;
      
      .seat-item {
        width: 100%;
        min-height: 240rpx;
        max-width: 100%;
        background: rgba(255, 255, 255, 0.95);
        border-radius: 14rpx;
        padding: 16rpx;
        text-align: center;
        position: relative;
        transition: all 0.3s ease;
        box-shadow: 0 3rpx 12rpx rgba(0, 0, 0, 0.08);
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        box-sizing: border-box;
        overflow: hidden;
        
        .cube-container {
          margin-bottom: 12rpx;
          display: flex;
          justify-content: center;
          flex: 1;
          align-items: center;
        }
        
        .seat-info {
          .seat-id {
            display: block;
            font-size: 18rpx;
            color: #666;
            margin-bottom: 4rpx;
          }
          
          .seat-owner {
            display: block;
            font-size: 20rpx;
            color: #333;
            font-weight: bold;
            margin-bottom: 6rpx;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
          
          .seat-status {
            padding: 4rpx 8rpx;
            border-radius: 6rpx;
            font-size: 16rpx;
            font-weight: bold;
            
            &.status-idle { background: #d4edda; color: #155724; }
            &.status-occupy { background: #cce5ff; color: #004085; }
            &.status-ready { background: #fff3cd; color: #856404; }
            &.status-prepare { background: #d1ecf1; color: #0c5460; }
            &.status-plan { background: #e2e3e5; color: #383d41; }
            &.status-matching { background: #d4edda; color: #155724; }
            &.status-end { background: #f8d7da; color: #721c24; }
            &.status-error { background: #f8d7da; color: #721c24; }
          }
        }
      }
    }
    
    // 通用样式
    .seat-item {
      cursor: pointer;
      user-select: none;
      
      &:hover {
        transform: translateY(-4rpx);
        box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.2);
      }
      
      &:active {
        transform: translateY(-2rpx);
        box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.15);
      }
      
      &.current-user {
        border: 3rpx solid #667eea;
        background: rgba(102, 126, 234, 0.1);
        
        &:hover {
          border-color: #5a6fd8;
          background: rgba(102, 126, 234, 0.15);
        }
      }
      
      &.active {
        border: 3rpx solid #28a745;
        background: rgba(40, 167, 69, 0.1);
        
        &:hover {
          border-color: #218838;
          background: rgba(40, 167, 69, 0.15);
        }
      }
      
      // 空闲席位特殊样式
      &.status-idle {
        &:hover {
          border: 3rpx solid #28a745;
          background: rgba(40, 167, 69, 0.05);
        }
      }
      
      // 状态标签交互样式
      .seat-status {
        transition: all 0.3s ease;
        position: relative;
        
        &:hover {
          transform: scale(1.05);
          box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
        }
        
        &:active {
          transform: scale(0.95);
        }
        
        // 为可点击的状态标签添加指示器
        &[style*="pointer"] {
          &::after {
            content: '↔';
            position: absolute;
            right: -4rpx;
            top: -4rpx;
            font-size: 16rpx;
            color: #667eea;
            opacity: 0.7;
            transition: opacity 0.3s ease;
          }
          
          &:hover::after {
            opacity: 1;
          }
        }
      }
      
      .current-user-badge {
        position: absolute;
        top: -8rpx;
        right: -8rpx;
        width: 32rpx;
        height: 32rpx;
        background: #667eea;
        color: #fff;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 18rpx;
        font-weight: bold;
        box-shadow: 0 2rpx 8rpx rgba(102, 126, 234, 0.3);
      }
    }
  }
}

.selected-seat-detail {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(255, 255, 255, 0.98);
  border-radius: 20rpx 20rpx 0 0;
  padding: 24rpx;
  box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.15);
  z-index: 1000;
  
  .detail-card {
    .detail-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20rpx;
      
      .detail-title {
        font-size: 28rpx;
        font-weight: bold;
        color: #333;
      }
      
      .close-btn {
        width: 48rpx;
        height: 48rpx;
        border: none;
        background: none;
        font-size: 32rpx;
        color: #999;
      }
    }
    
    .detail-content {
      margin-bottom: 20rpx;
      
      .detail-row {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 12rpx;
        
        .detail-label {
          font-size: 24rpx;
          color: #666;
        }
        
        .detail-value {
          font-size: 24rpx;
          color: #333;
          font-weight: 500;
        }
        
        .detail-status {
          padding: 4rpx 12rpx;
          border-radius: 12rpx;
          font-size: 20rpx;
          font-weight: bold;
          
          &.status-idle { background: #d4edda; color: #155724; }
          &.status-occupy { background: #cce5ff; color: #004085; }
          &.status-ready { background: #fff3cd; color: #856404; }
          &.status-prepare { background: #d1ecf1; color: #0c5460; }
          &.status-plan { background: #e2e3e5; color: #383d41; }
          &.status-matching { background: #d4edda; color: #155724; }
          &.status-end { background: #f8d7da; color: #721c24; }
          &.status-error { background: #f8d7da; color: #721c24; }
        }
      }
    }
    
    .detail-actions {
      display: flex;
      gap: 16rpx;
      
      .action-btn {
        flex: 1;
        height: 80rpx;
        border: none;
        border-radius: 12rpx;
        font-size: 26rpx;
        font-weight: bold;
        
        &.primary {
          background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
          color: #fff;
        }
        
        &.secondary {
          background: #f8f9fa;
          color: #666;
          border: 2rpx solid #eee;
        }
      }
      
      // 蓝牙控制区域样式
      .ble-controls {
        width: 100%;
        margin-top: 20rpx;
        
        .ble-control-title {
          font-size: 24rpx;
          font-weight: bold;
          color: #333;
          margin-bottom: 16rpx;
          text-align: center;
        }
        
        .ble-control-buttons {
          display: flex;
          gap: 12rpx;
          margin-bottom: 16rpx;
          
          .ble-btn {
            flex: 1;
            height: 60rpx;
            border: none;
            border-radius: 8rpx;
            font-size: 22rpx;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s ease;
            
            &.connect {
              background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
              color: #fff;
              
              &:disabled {
                background: #6c757d;
                cursor: not-allowed;
              }
            }
            
            &.disconnect {
              background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
              color: #fff;
              
              &:disabled {
                background: #6c757d;
                cursor: not-allowed;
              }
            }
            
            &.reset {
              background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%);
              color: #333;
              
              &:disabled {
                background: #6c757d;
                cursor: not-allowed;
              }
            }
          }
        }
        
        .ble-status {
          background: #f8f9fa;
          border-radius: 8rpx;
          padding: 12rpx;
          
          .status-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 8rpx;
            
            &:last-child {
              margin-bottom: 0;
            }
            
            .status-label {
              font-size: 20rpx;
              color: #666;
            }
            
            .status-value {
              font-size: 20rpx;
              font-weight: bold;
              
              &.connected {
                color: #28a745;
              }
            }
          }
        }
      }
    }
  }
}

.bluetooth-section {
  margin-top: 30rpx;
  
  .bluetooth-card {
    background: rgba(255, 255, 255, 0.95);
    border-radius: 16rpx;
    padding: 24rpx;
    box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
    
    .bluetooth-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 16rpx;
      
      .bluetooth-title {
        font-size: 26rpx;
        font-weight: bold;
        color: #333;
      }
      
      .bluetooth-status {
        display: flex;
        align-items: center;
        gap: 8rpx;
        padding: 6rpx 12rpx;
        border-radius: 12rpx;
        font-size: 20rpx;
        font-weight: bold;
        
        .status-dot {
          width: 10rpx;
          height: 10rpx;
          border-radius: 50%;
        }
        
        &.connected {
          background: rgba(76, 175, 80, 0.2);
          color: #4caf50;
          
          .status-dot {
            background: #4caf50;
          }
        }
        
        &.disconnected {
          background: rgba(244, 67, 54, 0.2);
          color: #f44336;
          
          .status-dot {
            background: #f44336;
          }
        }
      }
    }
    
    .bluetooth-actions {
      display: flex;
      gap: 12rpx;
      margin-bottom: 16rpx;
      
      .bluetooth-btn {
        flex: 1;
        height: 60rpx;
        border: none;
        border-radius: 12rpx;
        font-size: 24rpx;
        font-weight: bold;
        color: #fff;
        background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
        
        &.disconnect {
          background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
        }
        
        &:disabled {
          opacity: 0.6;
        }
      }
    }
    
    .device-info {
      display: flex;
      flex-direction: column;
      gap: 6rpx;
      
      .device-name,
      .device-version,
      .device-battery {
        font-size: 22rpx;
        color: #666;
      }
    }
  }
}



@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

// 席位状态切换模态框样式
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.picker-modal-content {
  width: 80%;
  max-height: 70%;
  background: #fff;
  border-radius: 20rpx;
  overflow: hidden;
  position: relative;
  z-index: 10001;
  
  .picker-modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 30rpx;
    border-bottom: 2rpx solid #eee;
    background: #f8f9fa;
    
    .picker-modal-title {
      font-size: 32rpx;
      font-weight: bold;
      color: #333;
    }
    
    .close-btn {
      width: 60rpx;
      height: 60rpx;
      border: none;
      background: none;
      font-size: 40rpx;
      color: #999;
      cursor: pointer;
    }
  }
  
  .modal-body {
    padding: 30rpx;
    
    .current-status-info {
      display: flex;
      align-items: center;
      margin-bottom: 30rpx;
      padding: 20rpx;
      background: #f8f9fa;
      border-radius: 12rpx;
      
      .info-label {
        font-size: 28rpx;
        color: #333;
        font-weight: bold;
        margin-right: 15rpx;
      }
      
      .info-value {
        font-size: 28rpx;
        color: #333;
        font-weight: 500;
      }
      
      .status-badge {
        padding: 8rpx 20rpx;
        border-radius: 20rpx;
        font-size: 24rpx;
        font-weight: bold;
        
        // 房间状态样式
        &.status-wait { background: #fff3cd; color: #856404; }
        &.status-prepare { background: #d1ecf1; color: #0c5460; }
        &.status-countdown { background: #d4edda; color: #155724; }
        &.status-start { background: #cce5ff; color: #004085; }
        &.status-stop { background: #f8d7da; color: #721c24; }
        &.status-pause { background: #fff3cd; color: #856404; }
        &.status-cancel { background: #f8d7da; color: #721c24; }
        &.status-error { background: #f8d7da; color: #721c24; }
        &.status-unknown { background: #e2e3e5; color: #383d41; }
        
        // 席位状态样式
        &.status-idle { background: #d4edda; color: #155724; }
        &.status-occupy { background: #cce5ff; color: #004085; }
        &.status-ready { background: #fff3cd; color: #856404; }
        &.status-prepare { background: #d1ecf1; color: #0c5460; }
        &.status-plan { background: #e2e3e5; color: #383d41; }
        &.status-matching { background: #d4edda; color: #155724; }
        &.status-end { background: #f8d7da; color: #721c24; }
        &.status-error { background: #f8d7da; color: #721c24; }
      }
    }
    
    .next-status-section {
      .section-title {
        font-size: 28rpx;
        color: #333;
        font-weight: bold;
        margin-bottom: 20rpx;
        display: block;
      }
      
      .status-options {
        .status-option {
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding: 25rpx;
          border: 2rpx solid #eee;
          border-radius: 12rpx;
          margin-bottom: 15rpx;
          transition: all 0.3s ease;
          cursor: pointer;
          
          &:hover {
            border-color: #667eea;
            background: #f8f9fa;
          }
          
          &.selected {
            border-color: #667eea;
            background: #e3f2fd;
            border-left: 4rpx solid #667eea;
          }
          
          .option-text {
            font-size: 28rpx;
            color: #333;
            font-weight: 500;
          }
          
          .option-check {
            font-size: 32rpx;
            color: #667eea;
            font-weight: bold;
          }
        }
      }
    }
  }
  
  .modal-footer {
    display: flex;
    gap: 20rpx;
    padding: 30rpx;
    border-top: 2rpx solid #eee;
    
    .cancel-btn, .submit-btn {
      flex: 1;
      height: 80rpx;
      border: none;
      border-radius: 12rpx;
      font-size: 28rpx;
      font-weight: bold;
      cursor: pointer;
      
      &.cancel-btn {
        background: #f8f9fa;
        color: #666;
        border: 2rpx solid #eee;
      }
      
      &.submit-btn {
        background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
        color: #fff;
        
        &:disabled {
          opacity: 0.6;
          cursor: not-allowed;
        }
      }
    }
  }
}

@media screen and (orientation: landscape) {
  .picker-modal-content {
    width: 100%;
    max-height: none;
    height: 100%;
    border-radius: 0;
    display: flex;
    flex-direction: column;
  }

  .picker-modal-content .modal-body {
    flex: 1;
    overflow: auto;
  }
}
.fallback-cube-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 30rpx;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 16rpx;
  box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
  
  .fallback-text {
    font-size: 24rpx;
    color: #666;
    margin-top: 20rpx;
  }
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style> 